package com.github.live.component;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.os.Handler;
import android.util.ArrayMap;

import com.alibaba.fastjson.JSONObject;
import com.github.live.manager.ChannelsManager;
import com.github.live.manager.LiveInitializer;
import com.github.live.util.HandlerWrapper;
import com.github.live.util.LogFactory;
import com.github.livebase.bean.Channel;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import xyz.doikki.videoplayer.player.LiveVideoView;
import xyz.doikki.videoplayer.player.VideoView;

/**
 * @ClassName Retry
 * @description: 超时换源 和 失败重试的逻辑
 * @author: biao532
 * @create: 2023-12-22 16:52
 * @Version 1.0
 **/
public class ErrorRetry implements LiveVideoView.StateChangeListener {
    private static final String[] STATE = new String[] {
            "ERROR", "IDLE", "PREPARING", "PREPARED", "PLAYING", "PAUSED", "PLAYBACK_COMPLETED",
            "BUFFERING", "BUFFERED", "START_ABORT", "", "", "", "", ""
    };
    private int currentLiveChangeSourceTimes;
    private ChannelsManager channelsManager;
    private HandlerWrapper mHandler;
    private LiveVideoView mVideoView;
    private int status;
    private Context mContext;
    private long start = 0;
    private final Runnable mConnectTimeoutChangeSourceRun = new Runnable() {
        @Override
        public void run() {
            // 无网络，不切频道不切源
            if (!chkNet()) {
                return;
            }
            currentLiveChangeSourceTimes++;
            // 切源
            if (channelsManager.getCurrentChannel().getSources().size() > currentLiveChangeSourceTimes) {
                removeRunning();
                channelsManager.nextSource();
                return;
            }
            // 切频道
            reset();
            if (channelsManager.getDirection() == ChannelsManager.DIRECTION_DOWN) {
                channelsManager.nextChannel();
            }
            else if (channelsManager.getDirection() == ChannelsManager.DIRECTION_UP) {
                channelsManager.preChannel();
            }
        }
    };

    private final Runnable mRetryConnect = new Runnable() {
        @Override
        public void run() {
            if (ErrorRetry.this.status != VideoView.STATE_PLAYING
                    && ErrorRetry.this.status != VideoView.STATE_BUFFERED) {
                // 网络有效，刷新视频， 无效则继续检测
                if (chkNet()) {
                    mVideoView.replay(false);
                }
                mHandler.postDelayed(this, getBuffingWaitfor());
            }
        }
    };

    public ErrorRetry(Handler handler, Context context, LiveVideoView view) {
        this.mHandler = new HandlerWrapper(handler);
        this.mVideoView = view;
        this.mContext = context;
        channelsManager = LiveInitializer.getInitializer().getChannelsManager();
    }

    public void reset() {
        this.currentLiveChangeSourceTimes = 0;
        removeRunning();
    }

    @Override
    public void onPlayStateChanged(int playState) {
        this.status = playState;
        LogFactory.debug(ErrorRetry.class, "player status=[{}]", STATE[playState+1]);
        switch (playState) {
            case VideoView.STATE_PREPARING: {
                start = System.currentTimeMillis();
            }
            case VideoView.STATE_BUFFERING:
                onBuffing();
                break;
            case VideoView.STATE_BUFFERED:
            case VideoView.STATE_PLAYING:
                onPlay();
                break;
            case VideoView.STATE_PLAYBACK_COMPLETED:
                onCompleted();
                break;
            case VideoView.STATE_ERROR:
                onError();
                break;
        }
    }

    private void onBuffing() {
        // 开启超时换源 监听
        if (mHandler.contains(mConnectTimeoutChangeSourceRun)) {
            return;
        }
        if (channelsManager.isLive()) {
            mHandler.postDelayed(mRetryConnect, getBuffingWaitfor());
        }

        mHandler.removeCallbacks(mConnectTimeoutChangeSourceRun);
        mHandler.postDelayed(mConnectTimeoutChangeSourceRun, getTimeoutDelay());
    }

    private void onPlay() {
        // 正常播放， 移除超时换源 和 超时重试
        removeRunning();
    }

    private void onCompleted() {
        LogFactory.debug(ErrorRetry.class, "completed");
        // 原因是网络连接失败
        if (!chkNet()) {
            mHandler.postDelayed(mRetryConnect, getBuffingWaitfor());
            return;
        }

        // 回看播放完成 / 直播网络错误
        if (channelsManager.isLive()) {
            // 直播网络错误， 开启重试
            if (!mHandler.contains(mConnectTimeoutChangeSourceRun)) {
                // 是否存在这个计时器？, 存在的不需要启动
                mHandler.postDelayed(mConnectTimeoutChangeSourceRun, getTimeoutDelay());
            }
            // 开启重试
            mHandler.postDelayed(mRetryConnect, getBuffingWaitfor());
        }
        else {
            removeRunning();
            // 回看播放完成，移除超时监听
            channelsManager.replayOver();
        }
    }

    private void onError() {
        removeRunning();
        // 发生错误

        // 原因是网络连接失败
        if (!chkNet()) {
            mHandler.postDelayed(mRetryConnect, getBuffingWaitfor());
            return;
        }

        // 直播
        if (channelsManager.isLive()) {
            // 立即换源
            mHandler.post(mConnectTimeoutChangeSourceRun);
        }
        else {
            // 结束回看
            channelsManager.replayOver();
        }
    }

    private long getTimeoutDelay() {
        return (LiveInitializer.getInitializer()
                .getSettingManager()
                .getTimeoutIndex() + 1) * 5000;
    }

    private long getBuffingWaitfor() {
        return LiveInitializer.getInitializer()
                .getConfig()
                .getBufferingWaitfor();
    }

    private void removeRunning() {
        mHandler.removeCallbacks(this.mRetryConnect);
        mHandler.removeCallbacks(this.mConnectTimeoutChangeSourceRun);
    }
    /**
     * 检测网络
     * @return
     */
    public boolean chkNet() {
        ConnectivityManager connectMgr = (ConnectivityManager) mContext.getApplicationContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectMgr == null) {
            return false;
        }
        Network net = connectMgr.getActiveNetwork();
        if (net == null) {
            return false;
        }
        NetworkCapabilities c = connectMgr.getNetworkCapabilities(net);
        return c.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
    }

}
